﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AliyunOss;
using Kalman;
using Kalman.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing;

namespace QuDao.Api.Controllers
{
    /// <summary>
    /// 文件上传API
    /// </summary>
    [AllowAnonymous]
    public class FileController : ApiControllerBase
    {
        readonly AliyunOssClient oss;
        public FileController(AliyunOssClient aliyunOssClient)
        {
            oss = aliyunOssClient;
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="hexString">十六进制数据</param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        [HttpPost]
        public FileDto UploadImageByHex([FromBody] string hexString, int maxWidth = 1080)
        {
            if (hexString.IsNullOrEmpty()) throw new AppException("无效的数据");
            var data = new byte[hexString.Length / 2];
            for (var x = 0; x < data.Length; x++)
            {
                var i = Convert.ToInt32(hexString.Substring(x * 2, 2), 16);
                data[x] = (byte)i;
            }

            if (maxWidth < 100 || maxWidth > 2000) throw new AppException("最大宽度数值无效，取值范围在100-2000之间");

            //byte[] data = base64Image.ToBytes();
            var fileID = IDGenerator.Instance.GetFileID();
            //var extName = Path.GetExtension(file.FileName);
            var extName = ".png";

            var dto = new FileDto
            {
                FileID = fileID,
            };

            using (var stream = new MemoryStream(data))
            {
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                dto.Width = img.Width;
                dto.Height = img.Height;
                if (img.Width > maxWidth) //自动转换图片大小
                {
                    img.Mutate(o =>
                    {
                        o.Resize(maxWidth, dto.Height * maxWidth / img.Width);
                    });
                }

                using var ms = new MemoryStream();
                switch (format)
                {
                    case GifFormat:
                        extName = ".gif";
                        img.SaveAsGif(ms);
                        break;
                    case JpegFormat:
                        extName = ".jpg";
                        img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                        break;
                    case PngFormat:
                    default:
                        extName = ".png";
                        img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                }
                ms.Seek(0, SeekOrigin.Begin);

                dto.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                dto.OssUrl = oss.Options.BindDomainUrl + dto.OssKey;
                dto.FileSize = (int)ms.Length;
                dto.HashCode = oss.PutImage(dto.OssKey, ms);
            }

            return dto;
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="file"></param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        [HttpPost]
        public FileDto UploadImage(IFormFile file, int maxWidth = 1080)
        {
            if (file == null) throw new AppException("无效的图片文件");
            if (maxWidth < 100 || maxWidth > 2000) throw new AppException("最大宽度数值无效，取值范围在100-2000之间");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(file.FileName);

            var dto = new FileDto
            {
                FileID = fileID,
                FileSize = file.Length
            };

            using (var stream = file.OpenReadStream())
            {
                using var img = Image.Load(stream);
                var format = img.Metadata.DecodedImageFormat;
                dto.Width = img.Width;
                dto.Height = img.Height;
                if (img.Width > maxWidth) //自动转换图片大小
                {
                    img.Mutate(o =>
                    {
                        o.Resize(maxWidth, dto.Height * maxWidth / img.Width);
                    });
                }

                using var ms = new MemoryStream();
                switch (format)
                {
                    case GifFormat:
                        extName = ".gif";
                        img.SaveAsGif(ms);
                        break;
                    case JpegFormat:
                        extName = ".jpg";
                        img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                        break;
                    case PngFormat:
                    default:
                        extName = ".png";
                        img.Save(ms, new PngEncoder {  CompressionLevel= PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                        break;
                }
                ms.Seek(0, SeekOrigin.Begin);

                dto.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                dto.OssUrl = oss.Options.BindDomainUrl + dto.OssKey;
                dto.FileSize = (int)ms.Length;
                dto.HashCode = oss.PutImage(dto.OssKey, ms);
            }

            return dto;
        }

        /// <summary>
        /// 批量上传图片
        /// </summary>
        /// <param name="files"></param>
        /// <param name="maxWidth">限制上传图片最大宽度（默认1080），超出会自动按最大宽度裁剪</param>
        [HttpPost]
        public IEnumerable<FileDto> UploadImageBatch(List<IFormFile> files, int maxWidth = 1080)
        {
            if (files == null || files.Count < 1) throw new AppException("图片文件不能为空");
            if (maxWidth < 100 || maxWidth > 1500) throw new AppException("最大宽度数值无效，取值范围在100-1200之间");

            var list = new List<FileDto>();
            foreach (var file in files)
            {
                var fileID = IDGenerator.Instance.GetFileID();
                var extName = Path.GetExtension(file.FileName);
                var dto = new FileDto
                {
                    FileID = fileID,
                    FileSize = file.Length
                };

                using (var stream = file.OpenReadStream())
                {
                    using var img = Image.Load(stream);
                    var format = img.Metadata.DecodedImageFormat;
                    dto.Width = img.Width;
                    dto.Height = img.Height;
                    if (img.Width > maxWidth) //自动转换图片大小
                    {
                        img.Mutate(o =>
                        {
                            o.Resize(maxWidth, dto.Height * maxWidth / img.Width);
                        });
                    }

                    using var ms = new MemoryStream();
                    switch (format)
                    {
                        case GifFormat:
                            extName = ".gif";
                            img.SaveAsGif(ms);
                            break;
                        case JpegFormat:
                            extName = ".jpg";
                            img.SaveAsJpeg(ms, new JpegEncoder { Quality = 75 });
                            break;
                        case PngFormat:
                            extName = ".png";
                            img.SaveAsPng(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                            break;
                        default:
                            extName = ".png";
                            img.Save(ms, new PngEncoder { CompressionLevel = PngCompressionLevel.DefaultCompression });//默认Level6压缩级别
                            break;
                    }
                    ms.Seek(0, SeekOrigin.Begin);

                    dto.OssKey = $"qudao/image-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                    dto.OssUrl = oss.Options.BindDomainUrl + dto.OssKey;
                    dto.FileSize = (int)ms.Length;
                    dto.HashCode = oss.PutImage(dto.OssKey, ms);
                }

                list.Add(dto);
            }

            return list;
        }

        /// <summary>
        /// 上传视频
        /// <param name="file">视频文件</param>
        /// </summary>
        [HttpPost]
        public FileDto UploadVideo(IFormFile file)
        {
            var maxSize = 20;
            var maxLength = maxSize * 1024 * 1024; //
            if (file == null) throw new AppException("无效的视频文件");
            if (file.Length > maxLength) throw new AppException($"视频文件大小不能超过{maxSize}兆");

            var fileID = IDGenerator.Instance.GetFileID();
            var extName = Path.GetExtension(file.FileName);

            var entity = new FileDto
            {
                FileID = fileID,
                FileSize = file.Length
            };

            using (var stream = file.OpenReadStream())
            {
                entity.OssKey = $"qudao/video-{DateTime.Now:yyyyMM}/{fileID}{extName}";
                entity.OssUrl = oss.Options.BindDomainUrl + entity.OssKey;
                entity.FileSize = stream.Length;
                entity.HashCode = oss.PubObject(entity.OssKey, stream);
            }

            return entity;
        }

        ///// <summary>
        ///// 上传文件（上传图片请改用UploadImage接口）
        ///// </summary>
        ///// <param name="fileType">文件类型：image-图片（默认），video-视频，audio-音频，other-其他文件</param>
        ///// <param name="memo">文件备注</param>
        //[HttpPost]
        //public File Upload(string fileType = "image", string memo = "")
        //{
        //    if (Request.Form.Files.Count == 0) throw new AppException("上传文件不能为空");

        //    var file = Request.Form.Files[0];
        //    var extName = Path.GetExtension(file.FileName);

        //    var fileID = FileBO.GetNewID();
        //    var ossKey = $"farmstay/{fileType}-{DateTime.Now:yyyyMM}/{fileID}{extName}";

        //    var entity = new File
        //    {
        //        FileID = fileID,
        //        FileSize = (int)file.Length,
        //        FileType = fileType,
        //        OssKey = ossKey,
        //        OssUrl = appSettings.OssBaseUrl + ossKey,
        //        CreateTime = DateTime.Now,
        //        Memo = memo
        //    };

        //    using (var stream = file.OpenReadStream())
        //    {
        //        entity.HashCode = fileType switch
        //        {
        //            "image" => oss.PutImage(ossKey, stream),
        //            _ => oss.PubObject(ossKey, stream),
        //        };
        //    }

        //    FileBO.Instance.Add(entity);
        //    return entity;
        //}

        ///// <summary>
        ///// 批量上传文件（批量上传图片请改用UploadImageBatch接口）
        ///// </summary>
        ///// <param name="fileType">文件类型：image-图片（默认），video-视频，audio-音频，other-其他文件</param>
        ///// <param name="memo">文件备注</param>
        //[HttpPost]
        //public IEnumerable<File> UploadBatch(string fileType = "image", string memo = "")
        //{
        //    if (Request.Form.Files.Count == 0) throw new AppException("上传文件不能为空");

        //    var list = new List<File>();
        //    var files = Request.Form.Files;

        //    foreach (var file in files)
        //    {
        //        var extName = Path.GetExtension(file.FileName);

        //        var fileID = FileBO.GetNewID();
        //        var ossKey = $"farmstay/{fileType}-{DateTime.Now:yyyyMM}/{fileID}{extName}";

        //        var entity = new File
        //        {
        //            FileID = fileID,
        //            FileSize = (int)file.Length,
        //            FileType = fileType,
        //            OssKey = ossKey,
        //            OssUrl = appSettings.OssBaseUrl + ossKey,
        //            CreateTime = DateTime.Now,
        //            Memo = memo
        //        };

        //        using (var stream = file.OpenReadStream())
        //        {
        //            entity.HashCode = fileType switch
        //            {
        //                "image" => oss.PutImage(ossKey, stream),
        //                _ => oss.PubObject(ossKey, stream),
        //            };
        //        }

        //        list.Add(entity);
        //    }

        //    FileBO.Instance.BulkInsert(list);
        //    return list;
        //}

    }
}
